package com.wrial.utils;
/*
 * @Author  Wrial
 * @Date Created in 16:25 2020/3/27
 * @Description 手写HashMap
 */


import java.util.HashMap;

public class MyHashMap<K, V> {

    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
    static final float DEFAULT_LOAD_FACTOR = 0.75f;
    private int capicity;
    private float loadFactor;
    private int size = 0;
    Node<K, V>[] table;

    MyHashMap() {
        this.capicity = DEFAULT_INITIAL_CAPACITY;
        this.loadFactor = DEFAULT_LOAD_FACTOR;
    }

    MyHashMap(int capicity) {
        this.capicity = capicity <= 0 ? DEFAULT_INITIAL_CAPACITY : capicity;
        this.loadFactor = DEFAULT_LOAD_FACTOR;
    }

    public V put(K key, V value) {
        return this.putNode(myHash(key), key, value);
    }

    private int myHash(K key) {
        int bitMov;
        int hash = key == null ? 0 : ((bitMov = key.hashCode()) ^ (bitMov >>> 16));
        return hash;
    }

    public V putNode(int hash, K key, V value) {
        if (table == null) {
            resize();
        }
        int index = hash % capicity;
        if (table[index] == null) {
            table[index] = new Node<>(hash, key, value);
            size++;
        }if (table[index].key == key ){
            V oldVal = table[index].value;
            table[index].value = value;
            return oldVal;
        }else {
            Node<K, V> h = table[index];
            // 此时结束后就是没找到就要进行尾插
            while (h.next != null) {
                h = h.next;
                if (key.equals(h.key)) {
                    V oldVal = h.value;
                    h.value = value;
                    return oldVal;
                }
            }
            // 尾插
            Node newNode = new Node(hash, key, value);
            h.next = newNode;
            size +=size;
        }

        // 表示插入成功
        return value;

    }


    // 初始化和扩容
    private void resize() {
        Node<K, V>[] temp = table;
        if (temp == null || temp.length == 0) {
            table = new Node[capicity];
            System.out.println("init");
        }
    }

    public V get(K key) {
        return getVal(key);
    }

    private V getVal(K key) {
        V temp = findKeyNode(key);
        return temp == null ? null : temp;
    }

    public int getSize() {
        return size;
    }

    public V findKeyNode(K key) {
        V res = null;
        int index = myHash(key);
        if (table[index].key.equals(key)) {
            res = table[index].value;
        } else {
            Node<K, V> head = table[index];
            while (head.next != null) {
                head = head.next;
                if (head.key == key) {
                    res = head.value;
                }
            }
        }
        return res;
    }


    class Node<K, V> {
        Node(int hash, K key, V value) {
            this.hash = hash;
            this.key = key;
            this.value = value;
        }

        int hash;
        K key;
        V value;
        Node<K, V> next;
    }


    public static void main(String[] args) {

        MyHashMap<Integer, Integer> myHashMap = new MyHashMap<>();
        Integer put = myHashMap.put(1, 1);
        System.out.println(myHashMap.put(1, 2));
        myHashMap.put(2, 3);
        System.out.println("get   "+myHashMap.get(1));
        System.out.println("get   "+myHashMap.get(2));
        System.out.println("size   "+myHashMap.getSize());


    }


}
